#ifndef CAFFEINE_UTILITY_PARSABLES_IPARSABLE_HPP
#define CAFFEINE_UTILITY_PARSABLES_IPARSABLE_HPP

#include "Common.hpp"
#include "Utility/Factory.hpp"
#include "Utility/Singleton.hpp"

#include <list>
#include <map>
#include <string>

namespace Utility
{
	namespace Parsables
	{
		class IParsable;

		enum PropertyType
		{
			PROPERTY_TYPE_STRING = 0,
			PROPERTY_TYPE_OBJECT
		};

		struct Property
		{
			Property( void )
				: type( PROPERTY_TYPE_STRING ), obj( 0 )
			{
			}

			int type;
			std::string str;
			IParsable *obj;
		};

		class IParsable
		{
		public:
			IParsable( void );
			virtual ~IParsable( void );

			virtual void Create( void );

			virtual bool HasProperty( const std::string &prop );
			virtual Property GetProperty( const std::string &prop );
			virtual void SetProperty( const std::string &propKey, Property &propVal );
			virtual void SetProperty( const std::string &propKey, const std::string &propVal );
			virtual void SetProperty( const std::string &propKey, IParsable *propVal );

			static void DestroyAll( void ) ;
		private:
			std::map< std::string, Property > properties;

			static std::list< IParsable * > parsablesList;
		};
	}

	typedef Factory< Parsables::IParsable > ParsablesFactory;
}

template< typename Type >
class DefineParsable
{
public:
	DefineParsable( const std::string parsable )
	{
		Utility::Singleton< Utility::ParsablesFactory >::Get()->Register( parsable, new Utility::Creator< Utility::Parsables::IParsable, Type >() );
	}

	~DefineParsable( void )
	{
	}
};	

#endif //CAFFEINE_UTILITY_PARSABLES_IPARSABLE_HPP